#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：Employment_class 
@File    ：04_协程.py
@IDE     ：PyCharm 
@Author  ：XiaoDengYa
@Date    ：2021/8/16/016 9:35 
"""

"""
def coroutine_example(name):
    print('start coroutine...name:', name)
    x = yield name  # 调用next()时，产出yield右边的值后暂停；调用send()时，产出值赋给x，并往下运行
    print('send值:', x)


coro = coroutine_example('Zarten')
print('next的返回值:', next(coro))
try:
    print('send的返回值:', coro.send(6))
except StopIteration:
    print("结束")

"""

"""
def coroutine_example(name):
    print('start coroutine...name:', name)

    while True:
        x = yield name  # 调用next()时，产出yield右边的值后暂停；调用send()时，产出值赋给x，并往下运行
        if x is None:
            return 'zhihuID: Zarten'
        print('send值:', x)


coro = coroutine_example('Zarten')
next(coro)
print('send的返回值:', coro.send(6))
try:
    coro.send(None)
except StopIteration as e:
    print('返回值：', e.value)
"""

# def for_test():
#     for i in range(3):
#         yield i
#
#
# print(list(for_test()))
#
#
# def yield_from_test():
#     yield from range(3)
#
#
# print(list(yield_from_test()))

#
# def coroutine_example(name):
#     print('start coroutine...name:', name)
#     x = yield name  # 调用next()时，产出yield右边的值后暂停；调用send()时，产出值赋给x，并往下运行
#     print('send值:', x)
#     return 'zhihuID: Zarten'
#
#
# def grouper2():
#     result2 = yield from coroutine_example('Zarten')  # 在此处暂停，等待子生成器的返回后继续往下执行
#     print('result2的值：', result2)
#     return result2
#
#
# def grouper():
#     result = yield from grouper2()  # 在此处暂停，等待子生成器的返回后继续往下执行
#     print('result的值：', result)
#     return result
#
#
# def main():
#     g = grouper()
#     next(g)
#     try:
#         g.send(10)
#     except StopIteration as e:
#         print('返回值：', e.value)
#
#
# if __name__ == '__main__':
#     main()

# 最简单的异步IO示例

"""
import asyncio

async def coroutine_example():
    await asyncio.sleep(1) # 模拟IO操作，这样的休眠不会阻塞事件循环，前面加上await后会把控制权交给主事件循环，在休眠（IO操作）结束后恢复这个协程。
    print('zhihu ID: Zarten')


coro = coroutine_example()

loop = asyncio.get_event_loop()
loop.run_until_complete(coro)  # 阻塞调用，直到协程运行结束才返回。参数是future，传入协程对象时内部会自动变为future
loop.close()
"""

"""
1.当我们给一个函数添加了async关键字，或者使用asyncio.coroutine装饰器装饰，就会把它变成一个异步函数。
2.每个线程有一个事件循环，主线程调用asyncio.get_event_loop时会创建事件循环，
3.将任务封装为集合asyncio.gather(*args),之后一起传入事件循环中
4.要把异步的任务丢给这个循环的run_until_complete方法，事件循环会安排协同程序的执行。和方法名字一样，该方法会等待异步的任务完全执行才会结束。
"""

#
#
# @asyncio.coroutine  # 设置为异步函数
# def func1(num):
#     print(num, 'before--func1--')
#     yield from asyncio.sleep(5)
#     print(num, 'after--func1--')
#
#
# task = [func1(1), func1(2)]
#
# if __name__ == '__main__':
#     begin = time.time()
#     loop = asyncio.get_event_loop()  # 进入事件循环
#     loop.run_until_complete(asyncio.gather(*task))  # 将协程程序注册到事件循环中
#     loop.close()
#     end = time.time()
#     print(end - begin)


#
# async def func1(num):  # 使用async关键字定义一个协程，协程也是一种对象，不能直接运行，需要加入事件循环中，才能被调用。
#     print(num, 'before---func1----')
#
#
# if __name__ == "__main__":
#     begin = time.time()
#
#     # coroutine = func1(2)
#     task = [func1(1), func1(2)]
#     loop = asyncio.get_event_loop()
#     loop.run_until_complete(asyncio.gather(*task))
#     loop.close()
#     end = time.time()
#     print(end - begin)

# 创建task
# async def func1(num):
#     print(num, 'before---func1----')
#
#
# if __name__ == "__main__":
#     begin = time.time()
#
#     coroutine = func1(2)
#
#     loop = asyncio.get_event_loop()
#
#     task = loop.create_task(coroutine)  # 创建了任务
#     print("task",task)  # pending
#
#     loop.run_until_complete(task)
#     loop.close()
#     print("task2",task)  # finished
#     end = time.time()
#     print(end - begin)
#
#
# # 绑定回调 add_done_callback
#
# async def func1(num):
#     print(num, 'before---func1----')
#     return "recv num %s" % num
#
#
# def callback(future):
#     print(future.result())
#
#
# if __name__ == "__main__":
#     begin = time.time()
#
#     coroutine1 = func1(1)
#     loop = asyncio.get_event_loop()
#     task1 = asyncio.ensure_future(coroutine1)
#     task1.add_done_callback(callback) # 绑定回调callback 并把func1 返回的值传给了他， future.result() 输出返回给他的结果
#     loop.run_until_complete(task1)
#     loop.close()
#     end = time.time()
#     print(end - begin)


# 我也可以不使用回调函数，单纯获取返回值
# 当task状态为finished时候，我们可以直接使用result方法（在future模块）获取返回值
# async def func1(num):
#     print(num, 'before---func1----')
#     return "recv num %s" % num
#
#
# if __name__ == "__main__":
#     begin = time.time()
#
#     coroutine1 = func1(1)
#     loop = asyncio.get_event_loop()
#     task1 = asyncio.ensure_future(coroutine1)
#     loop.run_until_complete(task1)
#     print(task1)
#     print(task1.result())
#     loop.close()
#     end = time.time()
#     print(end - begin)


# 阻塞和await，实现并发
# import asyncio
# import time
#
#
# async def func1(num):
#     print(num, 'before---func1----')
#     await asyncio.sleep(num)
#     return "recv num %s" % num
#
#
# if __name__ == "__main__":
#     begin = time.time()
#
#     coroutine1 = func1(5)
#     coroutine2 = func1(3)
#     loop = asyncio.get_event_loop()
#     task1 = asyncio.ensure_future(coroutine1)
#     task2 = asyncio.ensure_future(coroutine2)
#     tasks = asyncio.gather(*[task1, task2])  # gather可以实现同时注册多个任务，实现并发操作。wait方法使用一致
#     loop.run_until_complete(tasks)
#     loop.close()
#     end = time.time()
#     print(end - begin)


# import asyncio, aiohttp
#
#
# async def fetch_async(url):
#     print(url)
#     async with aiohttp.ClientSession() as session:
#         async with session.get(url) as resp:
#             print(resp.status)
#             print(await resp.text())
#
#
# tasks = [fetch_async('http://www.baidu.com/'), fetch_async('http://www.cnblogs.com/ssyfj/')]
#
# event_loop = asyncio.get_event_loop()
# results = event_loop.run_until_complete(asyncio.gather(*tasks))
# event_loop.close()


import asyncio
import time


async def func1(num):
    print(num, 'before---func1----')
    await asyncio.sleep(num)
    return "recv num %s" % num


async def main():
    coroutine1 = func1(5)
    coroutine2 = func1(3)
    coroutine3 = func1(4)

    tasks = [
        asyncio.ensure_future(coroutine1),
        asyncio.ensure_future(coroutine2),
        asyncio.ensure_future(coroutine3),
    ]

    dones, pendings = await asyncio.wait(tasks)

    for task in dones:  # 对已完成的任务集合进行操作
        print("Task ret: ", task.result())


if __name__ == "__main__":
    begin = time.time()

    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()
    end = time.time()
    print(end - begin)
